-
-
Notifications
You must be signed in to change notification settings - Fork 14.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos/thermald: add manual config generation #44923
Conversation
I'm not sure if it's worth adding almost 40 options for the small number of people that will actually use them. NixOS evaluation time is still about linear in the amount of options, and as long as that's not resolved I think it would be wise not to use options for every single thing. Although, probably in the long term we shouldn't refrain from adding lots of options for things. But we have no idea how long it will be until somebody comes up with a solution to the evaluation time problem (I've been thinking about it myself for a while now, I have an idea, but no implementation yet). As an alternative, see how I use a single option to represent the whole config in #41467, and then use this to generate a syntactically valid config file. This has the advantage of only using one option and not needing NixOS module adjustments with new versions, but the disadvantage of not being able to check for valid config settings with the module system. What still can be done is to use the package itself to check for valid config settings at build time (by running it with some config check option, if supported). @Vodurden What do you think about this? I'm fine with either adding all the options or doing it the alternate way. I'll start reviewing the code after this is cleared up. |
@infinisil: Ooh that's an interesting approach, if I understand it correctly you're building a small abstract syntax tree using nix's semantic types and using it to represent the configuration file which you then compile into the config. I'll give it a shot and see how the resulting code turns out. Though it is a shame not to be able to use the options system to it's fullest as I think we lose some of the documentation discoverability which |
I just had a quick look into this: With that in mind it seems like we're evaluating two options Use nixos optionsPros:
Cons:
Use a generic semantic type and compile it to configThis is the newly suggested option Pros:
Cons:
Use a specific semantic type and compile it to config
I had a look at this approach and realised I don't think I can implement it without basically re-implementing submodules! What to do?Overall I'm not sure what approach to take. I'm not a big fan of introducing a generic config syntax tree since it won't have any static checking and will fail at runtime if the config is incorrect. But I also don't want to slow down the evaluation time for everything. Ultimately I guess what I need to know is:
Given that is can't be validated my preference is to keep the current approach but I'm open to trying alternatives if that's not palatable :) |
Neat overview! So I now think that doing it the current way is probably better. The point that convinced me is that docs for the available options are really nice, especially because thermald's config file docs are kinda bad. The NixOS module can serve as a better replacement for them. Very nice first PR btw! I'll try to review the code today :) |
platformConfig = with types; submodule { | ||
options = { | ||
Name = mkOption { | ||
type = string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All string
s should be str
s instead, see
Lines 210 to 212 in 249ba3d
# Deprecated; should not be used because it quietly concatenates | |
# strings, which is usually not what you want. | |
string = separatedString ""; |
options = { | ||
Name = mkOption { | ||
type = string; | ||
description = "The name of this platform"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All descriptions should end with a .
}; | ||
|
||
ThermalSensors = mkOption { | ||
type = (listOf thermalSensorConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parens can be removed (applies to lots of other options as well)
|
||
Temperature = mkOption { | ||
type = int; | ||
description = "Temperature at which to take action"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to include the unit, which apparently is millidegree celsius after some digging in the source.
}; | ||
|
||
ControlType = mkOption { | ||
type = nullOr (enum [ "SEQUENTIAL" "PARALLEL" ]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the source I see that it doesn't matter whether these settings are upper-cased or lower-cased. So I think we should prefer to use a consistent casing (Type
above uses lower-cased). Not sure why they use this mix in the man page. I'd prefer lower-casing.
script = '' | ||
exec ${pkgs.thermald}/sbin/thermald \ | ||
--no-daemon \ | ||
${optionalString cfg.debug "--loglevel=debug"} \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be put into serviceConfig.ExecStart
directly, without the exec
''; | ||
}; | ||
|
||
configFile = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to name this option config
and introduce a new option configFile
, which will default to the generated config, but will then be overridable by the user. Then cfg.configFile
can also be passed directly to the exec script and to etc
.
|
||
platformConfig = with types; submodule { | ||
options = { | ||
Name = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options are named according to camelCase, so all of the first letters should be lower cased instead (except UUID).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we keep UUID as is? Or should it be uuid
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh actually a couple options seem to be using uuid
, so that's probably better
Name = mkOption { | ||
type = string; | ||
description = "The name of this platform"; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of options could use example values
|
||
ki = mkOption { | ||
type = string; | ||
description = "ki"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also a lot of options could use better descriptions, e.g. these ones. But it might be pretty hard to find out what these exactly represent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to give these better descriptions but I have no idea what they do. The documentation is pretty sparse on them and I'm assuming if you want to set them then you know what they are 👀
With that said if anyone knows what they do I'm happy to include a better description!
2ebaf00
to
6b35529
Compare
Thanks for doing such a detailed review! I've addressed the documentation issues as best I can. I'll follow up with some more changes in the next few days to address the XML generation and configuration naming issues. |
I'm reluctant about this. @infinisil already brought up the evaluation performance issue: the NixOS evaluation model is currently not very scalable, so adding dozens of service-specific options should be avoided. The other argument is (lack of) maintainability: we're basically replicating the entire thermald configuration language in NixOS, so every time thermald adds an option, we'd have to update the NixOS module to make it available to users. We also have to duplicate all option descriptions from the upstream documentation, which is also not very nice - it's better to just refer to the upstream docs. |
I think they're reasonable concerns but I am having a hard time deciphering what guidelines I should be following in situations like this. When I asked about this in irc it seemed like the preference for this sort of situation is to embed the configuration in the nix language, but now it seems like we'd prefer to just embed the configuration files? I'm happy to follow either approach but I'd really appreciate some clear and consistent guidelines around how to enable this sort of service configuration in nixos. It's probably worth noting that the upstream docs are fairly sparse and difficult to decipher but I guess that could be solved with some documentation PRs to thermald rather then doing it here in the option configuration. 🤔 |
6b35529
to
9182bb1
Compare
Ok! So in the interest of getting this merged I have removed the nixos option based configuration in favor of the proposed
I have separated the option based configuration into a separate commit available here: Vodurden@494d997 If we decide to merge the follow-up commit it would be backwards compatible with this change as it simply sets the default of My feeling is that hopefully it's not too controversial to merge the I've tested this @infinisil, @edolstra: Please let me know if there are any other concerns/blockers for getting this change merged and I'll do my best to resolve them as soon as I can! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think this is in the right direction, it's very common to have such an option for services. It can still be expanded to more powerful options later.
configFile = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = "the thermald manual configuration file."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 common options for modules in NixOS:
configFile
, typenullOr path
, represents the path to the config fileextraConfig
, typelines
, represents the contents of the config file, will be appended to a generated one.
Since it doesn't make much sense to have extraConfig
here (because appending to valid xml makes it invalid), I think it might be best to just have the configFile
option with the path type.
It's still easily possible to convert a string to a path by doing
services.thermald.configFile = builtins.toFile "thermald.conf" ''
<foo>
...
</foo>
''
${pkgs.thermald}/sbin/thermald \ | ||
--no-daemon \ | ||
${optionalString cfg.debug "--loglevel=debug"} \ | ||
${optionalString (cfg.configFile != null) "--config-file ${config.environment.etc."thermald/thermal-conf.xml".source.outPath}"} \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the above mentioned change, this would also become an easier --config-file ${cfg.configFile}
9182bb1
to
3b036e2
Compare
@infinisil: Using the Let me know if there's anything else blocking this PR from being merged |
thermald has two modes: zero-config and manual. Sometimes it is useful to manually configure thermald to achieve better thermal results or to give thermald a hand when detecting possible cooling options.
3b036e2
to
64223a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Motivation for this change
thermald has two modes: zero-config and manual. Sometimes it is useful to manually configure thermald to achieve better thermal results or to give thermald a hand when detecting possible cooling options.
I have tested this change on my own laptop running NixOS and observed significant improvements in the thermals of my laptop.
With this change manual thermald config can be encoded in
configuration.nix
. For example:I'm not sure if the naming is exactly what we want, particularly around
configFile.platforms
so I'd appreciate any input on how to make this more consistent with other NixOS modules.I'd also like some feedback on how to better implement
TripPoints.CoolingDevices
. At the moment I've implementedCoolingDevices
as a list but in the actual XML it simply allows for multipleCoolingDevice
entries underTripPoints
.Currently we do:
But if we want to mirror how the XML is actually represented it would be closer to do:
But I'm unsure how to get submodules to merge correctly given the above syntax. Any input would be appreciated :)
Things done
sandbox
innix.conf
on non-NixOS)nix-shell -p nox --run "nox-review wip"
./result/bin/
)nix path-info -S
before and after)